/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.planning.tactical;

import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
import nl.cloudfarming.client.area.field.FieldAction;
import nl.cloudfarming.client.model.Field;
import nl.cloudfarming.client.model.FieldPlan;
import nl.cloudfarming.client.model.PartField;
import nl.cloudfarming.client.model.ProductionUnit;
import nl.cloudfarming.client.util.PanelStyle;
import org.jdesktop.swingx.JXPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.lookup.ServiceProvider;

/**
 * Link field to Production Unit action. Opens a Panel to Link a production unit to a field. Will create a partfield in the process using Field.createPartFieldFrom(Field, ProductionUnit).
 * @author Gerben Feenstra
 */
@ServiceProvider(service = FieldAction.class)
public class LinkProductionUnitToFieldAction extends FieldAction {

    // STRING CONSTANTS 
    private static final String LINK_TO_CULTURE_ACTION_NAME = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.name");
    private static final String LABEL_PRODUCTION_UNIT = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.label.production_unit");
    private static final String LABEL_FIELD_PLAN = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.label.fieldplan");
    private static final String BUTTON_OK = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.button.ok.text");
    private static final String BUTTON_CANCEL = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.button.cancel.text");
    private static final String DIALOG_DISPLAY_NAME = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.display_name");    
    private static final String DIALOG_COMBOBOX_PRODUCTION_UNIT_DEFAULT_VALUE = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.combobox.field_plans.default_value");    
    private static final String DIALOG_COMBOBOX_FIELD_PLAN_DEFAULT_VALUE = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.combobox.production_units.default_value");    
    private static final String SUMMARY_DIALOG_TITLE = NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.summary_dialog.title");    
        
    private Dialog dlg;
    
    // Dialogs components
    private final JComboBox productionUnitsComboBox = new JComboBox();

    private final Field field;
    private JButton jButtonOK = getOkButton();
    private JButton jButtonCancel = getCancelButton();
    private TacticalPlanningService service;
              
    // Active fieldplan and production unit
    private FieldPlan selectedFieldPlan = null;
    private ProductionUnit selectedProductionUnit = null;
    
    public LinkProductionUnitToFieldAction(){
        super(LINK_TO_CULTURE_ACTION_NAME);        
        field = Utilities.actionsGlobalContext().lookup(Field.class);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        service = Lookup.getDefault().lookup(TacticalPlanningService.class);
        
        JXPanel panel = new JXPanel(new MigLayout("wrap 2"));
        
        // Introtekst #1        
        panel.add(new JLabel(NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action.link_production_unit_to_field.dialog.introtekst1", field.getId(), field.getName() )), PanelStyle.INTROTEKST_TOP);
        
        // Introtekst #2
        panel.add(new JLabel(NbBundle.getMessage(LinkProductionUnitToFieldAction.class, "action_link_production_unit_to_field.dialog.introtekst2")), PanelStyle.INTROTEKST_BOTTOM);
        
        // Fieldplan ComboBox
        panel.add(new JLabel(LABEL_FIELD_PLAN));
        panel.add(getFieldPlanComboBox(), PanelStyle.GAP_LABEL_AND_COMPONENT);

        // ProductionUnit ComboBox
        panel.add(new JLabel(LABEL_PRODUCTION_UNIT));
        panel.add(getProductionUnitComboBox(), PanelStyle.GAP_LABEL_AND_COMPONENT);

        // Create the dialog and add the ok and cancel buttons
        DialogDescriptor dd = new DialogDescriptor(panel, DIALOG_DISPLAY_NAME);
        
        // OK and Cancel-Buttons
        dd.setOptions(new Object[]{jButtonOK, jButtonCancel});
        
        dlg = DialogDisplayer.getDefault().createDialog(dd);
        dlg.setVisible(true);
    }

    /**
     * JComboBox with all fieldPlans
     * @return JComboBox with all fieldPlans
     */
    private JComboBox getFieldPlanComboBox() {
        
        final JComboBox fieldPlanSelection = new JComboBox();
        
        // Fieldplans comboBox
        List<FieldPlan> fieldPlans = service.findAllFieldPlans();

        if (fieldPlans.isEmpty()) {
            fieldPlanSelection.setModel(new DefaultComboBoxModel(new String[]{DIALOG_COMBOBOX_PRODUCTION_UNIT_DEFAULT_VALUE }));
            fieldPlanSelection.setEnabled(false);
        } else {           
            fieldPlanSelection.setModel(new DefaultComboBoxModel(fieldPlans.toArray()));         
            
            // Listen for model selection change
            fieldPlanSelection.addItemListener(new ItemListener() {
                
                @Override
                public void itemStateChanged(ItemEvent e) {
                    Object possibleFP = fieldPlanSelection.getSelectedItem();
                    if(possibleFP instanceof FieldPlan){
                        selectedFieldPlan = (FieldPlan) possibleFP;     
                        jButtonOK.setEnabled(false);

                        // Selection changed, reload Production Unit combobox
                        createProductionUnitCBModel();
                    }
                }
            });
            
            // Set first fieldplan as selectedItem 
            selectedFieldPlan = fieldPlans.get(0);
            ((DefaultComboBoxModel) fieldPlanSelection.getModel()).setSelectedItem(selectedFieldPlan);
            
            // Enable ComboBox
            fieldPlanSelection.setEnabled(true);
        }
        return fieldPlanSelection;
    }

    /**
     * JComboBox with all ProductionUnits belonging to the selected fieldplan.
     * @return JComboBox with all ProductionUnits belonging to the selected fieldplan.
     */
    private JComboBox getProductionUnitComboBox() {

        // Fieldplans comboBox
        productionUnitsComboBox.setModel(createProductionUnitCBModel());
        productionUnitsComboBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {   
                Object possiblePU = productionUnitsComboBox.getSelectedItem();
                if(possiblePU instanceof ProductionUnit){ // SelectedItem can be default-value ( = String) when there are no PU's found for the selected Fieldplan
                    selectedProductionUnit = (ProductionUnit) possiblePU;
                    jButtonOK.setEnabled(true);
                }
            }
        });
        return productionUnitsComboBox;
    }

    /**
     * Init (or re-init) ProductionUnit ComboBoxModel
     */
    private DefaultComboBoxModel createProductionUnitCBModel() {
        selectedProductionUnit = null;
        
        DefaultComboBoxModel productionUnitComboBoxModel = (DefaultComboBoxModel) productionUnitsComboBox.getModel();
        
        // When model is initially created the model will still be null, create here
        if(productionUnitComboBoxModel == null){
            productionUnitComboBoxModel = new DefaultComboBoxModel();
            productionUnitsComboBox.setModel(productionUnitComboBoxModel);
        }
            
        // Find all productions units that belong to the selected fieldplan    
        List<ProductionUnit> productionUnits = service.findProductionUnitsByFieldPlan(selectedFieldPlan);
        
        if (productionUnits.isEmpty()) {
            productionUnitComboBoxModel.removeAllElements();
            productionUnitComboBoxModel.addElement(DIALOG_COMBOBOX_FIELD_PLAN_DEFAULT_VALUE);
            productionUnitsComboBox.setEnabled(false);
            jButtonOK.setEnabled(false);
        } else {
            productionUnitComboBoxModel.removeAllElements();
            for(ProductionUnit productionUnit : productionUnits){
                productionUnitComboBoxModel.addElement(productionUnit);
            }
            productionUnitsComboBox.setEnabled(true);
            jButtonOK.setEnabled(true);
            
            // Set first to active
            selectedProductionUnit = productionUnits.get(0);
        }
        return productionUnitComboBoxModel;
    }
    
    /**
     * Creates the dialog ok button
     * @return The OK button
     */
    private JButton getOkButton() {
        jButtonOK = new JButton();
        jButtonOK.setText(BUTTON_OK);
        jButtonOK.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                if (selectedProductionUnit != null) {
                    // Link PU to Field
                    PartField partField = Field.createPartFieldFrom(field, selectedProductionUnit);
                    partField.setField(field);
                    partField.setProductionUnit(selectedProductionUnit);
                    selectedProductionUnit.getPartFields().add(partField);
                    service.createNewPartField(partField);
                } else {
                    return;
                }
            }
        });
        return jButtonOK;
    }

    /**
     * creates the dialog cancel button
     * @return The cancel button
     */
    private JButton getCancelButton() {
        jButtonCancel = new JButton();
        jButtonCancel.setText(BUTTON_CANCEL);
        jButtonCancel.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                dlg.setVisible(false);
                dlg = null;
            }
        });
        return jButtonCancel;
    }
}
